package com.lt.integration.jpa.component;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.lt.integration.jpa.component.common.Direction;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import javax.persistence.metamodel.Attribute;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 基础查询类 名词解释：query object 简称 qo
 *
 * @author weidian
 */
@ApiModel("查询基类")
public class BaseQO implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 实体ID
     */
    @ApiModelProperty("编号")
    private Long id;

    /**
     * 实体ID集合
     */
    @ApiModelProperty(hidden = true)
    private List<Long> ids;

    /**
     * 不包含的ID集合
     */
    @ApiModelProperty(hidden = true)
    private List<Long> excludeIds;
    /**
     * 需要保留的字段
     * 如果不设置 保留所有字段
     */
    @JsonIgnore
    @ApiModelProperty(hidden = true)
    private List<Attribute<?, ?>> attributes;

    @ApiModelProperty("页码")
    private int pageNo = 1;

    @ApiModelProperty(value = "每页大小")
    private int pageSize = 10;

    @ApiModelProperty(hidden = true)
    private Direction direction;

    @ApiModelProperty(hidden = true)
    private Long cursor;

    public void setCursor(Long id, Direction direction) {
        this.cursor = id;
        this.direction = direction;
    }

    /**
     * 增加id
     *
     * @param id
     * @return
     */
    public BaseQO addIds(Long id) {
        if (null == ids) {
            ids = new ArrayList<>();
        }
        ids.add(id);
        return this;
    }

    /**
     * 设置id
     *
     * @param ids
     */
    public void setIds(List<Long> ids) {
        this.ids = ids;
    }

    /**
     * 增加不包含的id
     *
     * @param id
     * @return
     */
    public BaseQO addExcludeIds(Long id) {
        if (null == excludeIds) {
            excludeIds = new ArrayList<>();
        }
        excludeIds.add(id);
        return this;
    }

    /**
     * 增加需要保留的字段
     *
     * @param property
     * @return
     */
    public BaseQO addProperty(Attribute<?, ?> property) {
        if (null == attributes) {
            attributes = new ArrayList<>();
        }
        attributes.add(property);
        return this;
    }


    public List<String> getIncludeProperty() {
        if (null == attributes || attributes.size() == 0) {
            return null;
        }

        List<String> includeProperty = new ArrayList<>();

        for (Attribute<?, ?> attr : attributes) {
            includeProperty.add(attr.getName());
        }
        return includeProperty;
    }

    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        if (null == pageNo || pageNo < 1) {
            this.pageNo = 1;
        } else {
            this.pageNo = pageNo;
        }
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        if (null == pageSize || pageSize < 1) {
            this.pageSize = 10;
        } else {
            this.pageSize = pageSize;
        }
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public List<Long> getIds() {
        return ids;
    }

    public List<Long> getExcludeIds() {
        return excludeIds;
    }

    public List<Attribute<?, ?>> getAttributes() {
        return attributes;
    }

    public Long getCursor() {
        return cursor;
    }

    public Direction getDirection() {
        return direction;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        BaseQO baseQO = (BaseQO) o;

        if (pageNo != baseQO.pageNo) {
            return false;
        }
        if (pageSize != baseQO.pageSize) {
            return false;
        }
        if (id != null ? !id.equals(baseQO.id) : baseQO.id != null) {
            return false;
        }
        if (ids != null ? !ids.equals(baseQO.ids) : baseQO.ids != null) {
            return false;
        }
        if (excludeIds != null ? !excludeIds.equals(baseQO.excludeIds) : baseQO.excludeIds != null) {
            return false;
        }
        if (attributes != null ? !attributes.equals(baseQO.attributes) : baseQO.attributes != null) {
            return false;
        }
        if (direction != baseQO.direction) {
            return false;
        }
        return cursor != null ? cursor.equals(baseQO.cursor) : baseQO.cursor == null;
    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (ids != null ? ids.hashCode() : 0);
        result = 31 * result + (excludeIds != null ? excludeIds.hashCode() : 0);
//        result = 31 * result + (attributes != null ? attributes.hashCode() : 0);
        result = 31 * result + pageNo;
        result = 31 * result + pageSize;
        result = 31 * result + (direction != null ? direction.hashCode() : 0);
        result = 31 * result + (cursor != null ? cursor.hashCode() : 0);
        return result;
    }
}